package ru.susu.algebra.partition;

import java.util.ArrayList;
import java.util.List;

import ru.susu.algebra.cache.ISimpleCache;
import ru.susu.algebra.cache.SimpleHashMapCache;
import ru.susu.algebra.partition.filter.IPartitionFilter;

/**
 * @author akargapolov
 * @since: 26.02.2009
 */
public class PartitionsCacheConstructor implements IPartitionConstructor
{
	private static ISimpleCache _cache = new SimpleHashMapCache();

	@Override
	public List<Partition> getAscendingPartitions(Integer number, IPartitionFilter filter)
	{
		synchronized (_cache)
		{
			String key = this.getKey(number, filter);
			if (_cache.containsKey(key))
			{
				return (List<Partition>) _cache.getValue(key);
			}

			List<Partition> result = this.construct(number, filter);
			_cache.put(key, result);
			return result;
		}
	}

	private List<Partition> construct(int number, IPartitionFilter filter)
	{
		Integer length = PartitionEnumerator.getPartitionsNumber(number).intValue();
		List<Partition> result = new ArrayList<Partition>(length);
		if (number == 0)
			result.add(PartitionsFactory.createPartition(new Integer[0]));
		for (int order = 0; order < length; order++)
		{
			Partition partition = PartitionsFactory.createPartition(order, number);
			if (filter.checkPartition(partition))
				result.add(PartitionsFactory.createPartition(order, number));
		}
		return result;
	}

	private void construct(int start, int number, List<Partition> result, Partition partition, IPartitionFilter filter)
	{
		if (number == 0)
		{
			if (filter.checkPartition(partition))
			{
				result.add(partition.clone());
			}
		}
		else if (start <= number)
		{
			partition.add(start);
			this.construct(start, number - start, result, partition, filter);
			partition.remove(start);

			this.construct(start + 1, number, result, partition, filter);
		}
	}

	private String getKey(Integer number, IPartitionFilter filter)
	{
		StringBuffer res = new StringBuffer();
		res.append(filter.getClass().getName());
		res.append(number.toString());
		return res.toString();
	}

}
